package com.ziytek.web.citizen.service;

import com.ziytek.web.citizen.caffeine.CachePutOrGet;
import com.ziytek.web.citizen.config.caffeine.CaffeineUtil;
import com.ziytek.web.citizen.constant.JobConstant;
import com.ziytek.web.citizen.constant.NumConstant;
import com.ziytek.web.citizen.constant.ServerConstant;
import com.ziytek.web.citizen.constant.TableConstant;
import com.ziytek.web.citizen.enums.ErrorTypeEnum;
import com.ziytek.web.citizen.mapper.OperationDetailMapper;
import com.ziytek.web.citizen.mapper.TableMapper;
import com.ziytek.web.citizen.model.bean.InterruptStatsCacheVo;
import com.ziytek.web.citizen.model.rsp.R;
import com.ziytek.web.citizen.pojo.basic.OperationDetail;
import com.ziytek.web.citizen.quartz.QuartzService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * 指令中断或重连服务类
 *
 * @author fenghx
 */

@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class InterruptIssuedService {
    private final TableMapper tableMapper;
    private final QuartzService quartzService;
    private final CachePutOrGet cachePutOrGet;
    private final OperationDetailMapper operationDetailMapper;

    public List<OperationDetail> getOperationDetail(String cabinetNo) {
        var vos = StringUtils.isBlank(cabinetNo) ?
                operationDetailMapper.findDetailByStartFlag(ServerConstant.START_FLAG_NORMAL) :
                operationDetailMapper.findDetailByCabinetNoAndStartFlag(cabinetNo, ServerConstant.START_FLAG_NORMAL);

        return CollectionUtils.isEmpty(vos) ? Collections.emptyList() : vos;
    }

    public void interruptIssued() {
        log.info("服务停止保存工步信息");

        // todo 检查是否有工艺步骤在执行中
        List<OperationDetail> vos = getOperationDetail(null);
        log.info("服务停止保存工步信息,中断工步操作记录总数:{}", vos.size());
        if (CollectionUtils.isEmpty(vos)) {
            return;
        }

        interruptIssuedByList(vos);
    }

    public void interruptIssued(String cabinetNo) {
        if (StringUtils.isBlank(cabinetNo)) {
            interruptIssued();
            return;
        }

        log.info("机柜断连保存工步信息");

        // todo 检查是否有工艺步骤在执行中
        List<OperationDetail> vos = getOperationDetail(cabinetNo);
        log.info("机柜断连保存工步信息,中断工步操作记录总数:{},cabinetNo:{}", vos.size(), cabinetNo);
        if (CollectionUtils.isEmpty(vos)) {
            return;
        }

        interruptIssuedByList(vos);
    }

    private void interruptIssuedByList(List<OperationDetail> vos) {
        if (CollectionUtils.isEmpty(vos)) {
            return;
        }

        Long timeMillis = System.currentTimeMillis();
        // 更新中断时间
        for (var v : vos) {
            interruptIssuedByOperationDetail(v, timeMillis);
        }

        boolean has = !CollectionUtils.isEmpty(vos) && vos.stream().anyMatch(v -> null != v && ServerConstant.SINGLE_TYPE_ALL == v.getSingleType());
        // 是否有全部指令 有的删除定时任务
        if (has) {
            var v = vos.getFirst();
            var cacheKey = CaffeineUtil.getCacheKey(Integer.parseInt(v.getCabinetNo()), 255, 255, v.getOrderNo());
            CaffeineUtil.delete(CaffeineUtil.CACHE_KEY_COMMAND + cacheKey);
            log.info("中断删除全部指令定时任务成功,cacheKey:{}", cacheKey);
        }
    }

    public void interruptIssuedByOperationDetail(OperationDetail v, Long nowTime) {
        if (null == v) {
            return;
        }

        Long timeMillis = null != nowTime ? nowTime : System.currentTimeMillis();
        // 更新中断时间
        var key = v.getCabinetNo() + CaffeineUtil.CACHE_KEY_SYMBOL + v.getBoardAddress() + CaffeineUtil.CACHE_KEY_SYMBOL + v.getCellNum();
        var s = cachePutOrGet.getStatsCache(key);
        // 执行中或者已完成
        boolean isIngOrFinish = null != s && s.getV() > NumConstant.INT_TWO_THOUSAND &&
                (ErrorTypeEnum.EXECUTING.getCode() == s.getT() || ErrorTypeEnum.EXECUTION_COMPLETED.getCode() == s.getT());
        if (isIngOrFinish) {
            v.setInterruptCap(((Double) s.getC()).floatValue());
            v.setStartFlag(ServerConstant.START_FLAG_INTERRUPT);
            var tableName = TableConstant.TABLE_REAL_TIME + v.getBoardAddress();
            var rd = tableMapper.queryRealTimeLastAndBatchNo(tableName, Integer.parseInt(v.getCabinetNo()), v.getBoardAddress(), v.getCellNum(), v.getBatchNo());
            Long time = null != rd && null != rd.getTime() ? rd.getTime() : null;
            if (Objects.isNull(time)) {
                v.setInterruptTimeSecond(((Double) s.getTs()).longValue());
                log.info("从操作缓存获取中断时间:key-{}-{}", key, v.getInterruptTimeSecond());
            } else {
                v.setInterruptTimeSecond(time);
            }
        }
        v.setUpdateTime(timeMillis);
        int rs = operationDetailMapper.updateDetail(v);

        // 停止定时统计
        var deleteKey = CaffeineUtil.getCacheKey(Integer.parseInt(v.getCabinetNo()), v.getBoardAddress(), v.getCellNum());
        var deleteJobName = JobConstant.JOB_NAME_COMMAND + CaffeineUtil.CACHE_KEY_SYMBOL + deleteKey;
        R r = quartzService.deleteCronJob(deleteJobName);
        if (r == null || !ServerConstant.SUCCESS.equals(r.getCode())) {
            log.info("中断删除定时任务失败 jobName：{} r:{}", deleteJobName, r);
        }

        // 删除电流LIST缓存
        cachePutOrGet.deleteCurrent(key);

        if (null != s) {
            var interruptStatsCacheVo = new InterruptStatsCacheVo();
            interruptStatsCacheVo.setCap(s.getC());
            interruptStatsCacheVo.setTs(s.getTs());
            int t = ((int) s.getTs()) / NumConstant.INT_TEN;
            int y = ((int) s.getTs()) % NumConstant.INT_TEN;
            var interruptCount = y == NumConstant.INT_ZERO ? t : t + NumConstant.INT_ONE;
            interruptStatsCacheVo.setInterruptBeforeTimes(interruptCount);
            cachePutOrGet.putInterruptCapacityCache(key, interruptStatsCacheVo);
        }

        // 单个通道的删除定时任务
        if (ServerConstant.SINGLE_TYPE_SINGLE == v.getSingleType()) {
            var cacheKey = CaffeineUtil.getCacheKey(Integer.parseInt(v.getCabinetNo()), v.getBoardAddress(), v.getCellNum(), v.getOrderNo());
            CaffeineUtil.delete(CaffeineUtil.CACHE_KEY_COMMAND + cacheKey);
            log.info("中断删除单个指令定时任务成功,cacheKey:{}", cacheKey);
        }
    }
}
